package service

import (
	"errors"
	v1 "server_go/api/v1"
	"server_go/internal/model"
	"server_go/internal/repository"
	"server_go/pkg/md5"
	"strconv"
	"time"
)

type UserService interface {
	Register(req *v1.RegisterRequest) error
	Login(req *v1.LoginRequest) (*v1.LoginResponse, error)
	AddUser(req *v1.AddUserRequest) error
	DeleteUser(req *v1.DeleteUserRequest) (*v1.DeleteUserResponse, error)
	UpdateUser(req *v1.UpdateUserRequest) error
	GetUserByAccount(req *v1.GetUserProfileRequest) (*v1.GetUserProfileResponse, error)
	GetAllUser(req *v1.GetAllUserRequest) (*v1.GetAllUserResponse, error)
	UpdateUserProfile(req *v1.UpdateUserProfileReq) (*v1.UpdateUserProfileResp, error)
}

func NewUserService(
	service *Service,
	userRepository repository.UserRepository,
	fileRepo repository.FileRepository,
) UserService {
	return &userService{
		Service:        service,
		userRepository: userRepository,
		fileRepo:       fileRepo,
	}
}

type userService struct {
	*Service
	userRepository repository.UserRepository
	fileRepo       repository.FileRepository
}

func (s *userService) Register(req *v1.RegisterRequest) error {
	// 首先查询注册的账号是否存在
	resp, err := s.userRepository.GetUserByAccount(req.Account)
	// 发生了错误 返回错误
	if err != nil && !errors.Is(err, v1.ErrUserNotExist) {
		return err
	}
	if resp != nil {
		return v1.ErrUserAccountExist
	}
	// 密码使用md5加密

	// 没有的情况下 就创建模型
	user := &model.User{
		Account:  req.Account,
		Password: req.Password,
		Username: req.Username,
		Type:     2, // 用户类型是2
		Status:   2, // 管理员新增的时候用户状态正常

	}
	if err := s.userRepository.AddUser(user); err != nil {
		return err
	}
	return nil
}
func (s *userService) Login(req *v1.LoginRequest) (*v1.LoginResponse, error) {
	user, err := s.userRepository.GetUserByAccount(req.Account)
	if err != nil {
		return nil, err
	}
	// 这里是查到了用户 比对用户的密码
	if user.Password != md5.Md5(req.Password) {
		return nil, v1.ErrPasswordIncorrect
	}

	// 对比用户的信息
	if user.Status == v1.UserDisableStatus {
		return nil, v1.ErrUserDisable
	}

	if user.Status == v1.UserClosureStatus {
		return nil, v1.ErrUserClosure
	}
	token, err := s.jwt.GenToken(strconv.Itoa(int(user.ID)), user.Type, time.Now().Add(24*time.Hour))
	if err != nil {
		return nil, v1.ErrInternalServerError
	}

	// 如果用户有头像 从文件表中查找头像路径
	file, err := s.fileRepo.GetFileById(user.AvatarId)
	if err != nil && !errors.Is(err, v1.ErrFileNotExist) {
		return nil, err
	}

	avatarPath := ""

	if file != nil {
		avatarPath = file.FilePath
	}

	record := v1.GetUserProfileResponse{
		UserId:     int64(user.ID),
		Account:    user.Account,
		Username:   user.Username,
		Describe:   user.Describe,
		AvatarPath: avatarPath,
		UserType:   user.Type,
		Status:     user.Status,
		CreatedAt:  user.CreatedAt,
		UpdatedAt:  user.UpdatedAt,
	}

	return &v1.LoginResponse{Record: record, Token: token}, nil
}
func (s *userService) AddUser(req *v1.AddUserRequest) error {
	// 查询账号是否存在
	resp, err := s.userRepository.GetUserByAccount(req.Account)
	if err != nil && !errors.Is(err, v1.ErrUserNotExist) {
		return err
	}
	if resp != nil {
		return v1.ErrUserExist
	}
	if err := s.userRepository.AddUser(&model.User{
		Account:  req.Account,
		Password: md5.Md5(req.Password),
		Username: req.Username,
		Type:     2,
		Status:   1,
	}); err != nil {
		return err
	}
	return nil
}

func (s *userService) DeleteUser(req *v1.DeleteUserRequest) (*v1.DeleteUserResponse, error) {
	if _, err := s.userRepository.GetUserById(req.UserId); err != nil {
		return nil, err
	}
	if err := s.userRepository.DeleteUser(req.UserId); err != nil {
		return nil, err
	}
	return &v1.DeleteUserResponse{UserId: req.UserId}, nil
}
func (s *userService) UpdateUser(req *v1.UpdateUserRequest) error {
	resp, err := s.userRepository.GetUserById(req.UserId)
	if err != nil {
		return nil
	}
	if resp == nil {
		return v1.ErrTagNotExist
	}
	user := &model.User{
		Username: req.Username,
		Password: req.Password,
		Status:   req.Status,
		Describe: req.Describe,
	}
	if err := s.userRepository.UpdateUser(req.UserId, user); err != nil {
		return nil
	}
	return nil
}

func (s *userService) GetUserByAccount(req *v1.GetUserProfileRequest) (*v1.GetUserProfileResponse, error) {
	user, err := s.userRepository.GetUserByAccount(req.Account)
	if err != nil {
		return nil, err
	}

	// 如果用户有头像 从文件表中查找头像路径
	file, err := s.fileRepo.GetFileById(user.AvatarId)
	if err != nil && !errors.Is(err, v1.ErrFileNotExist) {
		return nil, err
	}

	avatarPath := ""

	if file != nil {
		avatarPath = file.FilePath
	}

	return &v1.GetUserProfileResponse{
		UserId:     int64(user.ID),
		Account:    user.Account,
		Username:   user.Username,
		Describe:   user.Describe,
		AvatarPath: avatarPath,
		UserType:   user.Type,
		Status:     user.Status,
		CreatedAt:  user.CreatedAt,
		UpdatedAt:  user.UpdatedAt,
	}, nil
}

func (s *userService) GetAllUser(req *v1.GetAllUserRequest) (*v1.GetAllUserResponse, error) {
	users, total, err := s.userRepository.GetAllUser(req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	resp := ConvertToGetUserResponses(users)

	return &v1.GetAllUserResponse{Total: total, Record: resp}, nil
}

func (s *userService) UpdateUserProfile(req *v1.UpdateUserProfileReq) (*v1.UpdateUserProfileResp, error) {
	if _, err := s.userRepository.GetUserById(req.UserId); err != nil {
		return nil, err
	}

	if err := s.userRepository.UpdateUser(req.UserId, &model.User{
		Username: req.Username,
		Describe: req.Describe,
	}); err != nil {
		return nil, err
	}

	return &v1.UpdateUserProfileResp{Username: req.Username, Describe: req.Describe}, nil
}

// ConvertToGetUserResponses 函数功能： 将数据库中的User结构体转换为GetUserProfileResponse结构体
// 时间复杂度：O(n)
func ConvertToGetUserResponses(users []*model.User) []v1.GetUserResponseData {
	resp := make([]v1.GetUserResponseData, len(users))
	for i, user := range users {
		var deletedAt interface{}
		if user.DeletedAt.Valid {
			deletedAt = user.DeletedAt.Time
		} else {
			deletedAt = nil
		}

		resp[i] = v1.GetUserResponseData{
			UserId:    int64(user.ID),
			Account:   user.Account,
			Username:  user.Username,
			Describe:  user.Describe,
			Status:    user.Status,
			CreatedAt: user.CreatedAt,
			UpdatedAt: user.UpdatedAt,
			DeletedAt: deletedAt,
		}
	}
	return resp
}
